﻿namespace Sharemarker.Common.DataAccess
{
    using System;
    using System.Data;
    using System.Data.Common;
    using System.Data.Linq;

    using log4net;

    /// <summary>
    /// 
    /// </summary>
    public class DataContextUnitOfWork : IUnitOfWork<DataContext>
    {
        #region Static Fields

        /// <summary>
        /// 
        /// </summary>
        private static readonly ILog Logger = LogManager.GetLogger(typeof(DataContextUnitOfWork));

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="DataContextUnitOfWork" /> class.
        /// </summary>
        /// <param name="contextFactory">The context factory.</param>
        public DataContextUnitOfWork(Func<DataContext> contextFactory)
        {
            this.ContextFactory = contextFactory;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the context factory.
        /// </summary>
        /// <value>
        /// The context factory.
        /// </value>
        protected Func<DataContext> ContextFactory { get; set; }

        /// <summary>
        /// Gets or sets the data context.
        /// </summary>
        /// <value>
        /// The data context.
        /// </value>
        protected DataContext DataContext { get; set; }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// Commits this instance.
        /// </summary>
        public void Commit()
        {
            if (this.DataContext == null)
            {
                return;
            }

            this.DataContext.SubmitChanges();
        }

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            this.DisposeInternal();
        }

        /// <summary>
        /// Disposes the internal.
        /// </summary>
        public void DisposeInternal()
        {
            using (DataContext objToRelease = this.GetDB())
            {
                if (objToRelease != null)
                {
                    DbConnection connection = objToRelease.Connection;
                    if (connection.State != ConnectionState.Closed)
                    {
                        connection.Close();
                        connection.Dispose();
                    }
                }
            }
        }

        /// <summary>
        /// Gets the DB.
        /// </summary>
        /// <returns></returns>
        public DataContext GetDB()
        {
            return this.DataContext ?? (this.DataContext = this.ContextFactory());
        }

        #endregion
    }
}